package logic

import (
	"context"
	redis2 "gitee.com/Cauchy_AQ/vxopen/model/redis"
	"gitee.com/Cauchy_AQ/vxopen/utils"
	"github.com/redis/go-redis/v9"
	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/mem"
	"strconv"
	"sync"
	"time"

	"gitee.com/Cauchy_AQ/vxopen/rpc/transform/internal/svc"
	"gitee.com/Cauchy_AQ/vxopen/rpc/transform/transform"

	"github.com/zeromicro/go-zero/core/logx"
)

var (
	// 历史数据，每天更新一次即可
	his  transform.CardData
	once sync.Once
)

type WsSystemInfoHandlerLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewWsSystemInfoHandlerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WsSystemInfoHandlerLogic {
	return &WsSystemInfoHandlerLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *WsSystemInfoHandlerLogic) WsSystemInfoHandler(in *transform.WsSysInfoReq) (*transform.WsSysInfoResp, error) {
	once.Do(func() {
		go func() {
			// 每天凌晨0点主动获取一次老数据 his，存在该文件中
			now := time.Now()
			timer := time.NewTicker(utils.GetNextDay(now).Sub(now))
			for {
				select {
				case <-timer.C:
					now = time.Now()
					timer.Reset(utils.GetNextDay(now).Sub(now))
					go updateCardData(l.svcCtx.RDB)
				}
			}
		}()
	})

	// 获取今日的实时的最新数据
	td := getCardDataFromRedis(l.svcCtx.RDB, false)
	// 获取总访问量和总点击量
	total, _ := l.svcCtx.RDB.PFCount(context.Background(), redis2.CacheVisitPrefix).Result()
	click, _ := l.svcCtx.RDB.Get(context.Background(), redis2.CacheClickPrefix).Result()
	loc, _ := time.LoadLocation("Asia/Shanghai")

	return &transform.WsSysInfoResp{
		CardList: &transform.CardList{
			Today:   &td,
			History: &his,
			Total:   strconv.FormatInt(total, 10),
			Click:   click,
		},
		MemCpuList: &transform.MemCpuList{
			Mem: getSystemMemoryUsage(),
			Cpu: &transform.CpuData{
				Usage: getSystemCpuUsage(),
				Time:  time.Now().In(loc).Format("15:04:05"),
			},
		},
	}, nil
}

func getSystemMemoryUsage() string {
	memPercent, _ := mem.VirtualMemory()
	return strconv.FormatFloat(memPercent.UsedPercent*0.01, 'f', 2, 64)
}

func getSystemCpuUsage() string {
	cpuPercent, _ := cpu.Percent(time.Second, false)
	return strconv.FormatFloat(cpuPercent[0], 'f', 2, 64)
}

func getCardDataFromRedis(rdb *redis.Client, isHistory bool) transform.CardData {
	cd := transform.CardData{
		Total:  "0",
		Online: "0",
		Click:  "0",
		Users:  "0",
	}

	if isHistory {
		total, _ := rdb.PFCount(context.Background(), redis2.CacheDayVisitPrefix+utils.GetYesterdayFormat()).Result()
		online, _ := rdb.Get(context.Background(), redis2.CacheMaxOnlinePrefix+utils.GetYesterdayFormat()).Result()
		click, _ := rdb.Get(context.Background(), redis2.CacheDayClickPrefix+utils.GetYesterdayFormat()).Result()
		users, _ := rdb.Get(context.Background(), redis2.CacheNewUsersPrefix+utils.GetLastMonth(time.Now())).Result()
		cd.Total = strconv.FormatInt(total, 10)
		if len(online) > 0 {
			cd.Online = online
		}
		if len(click) > 0 {
			cd.Click = click
		}
		if len(users) > 0 {
			cd.Users = users
		}
		his = cd
	} else {
		total, _ := rdb.PFCount(context.Background(), redis2.CacheDayVisitPrefix+utils.GetTodayFormat()).Result()
		click, _ := rdb.Get(context.Background(), redis2.CacheDayClickPrefix+utils.GetTodayFormat()).Result()
		users, _ := rdb.Get(context.Background(), redis2.CacheNewUsersPrefix+utils.GetMonth(time.Now())).Result()
		cd.Total = strconv.FormatInt(total, 10)
		if len(click) > 0 {
			cd.Click = click
		}
		if len(users) > 0 {
			cd.Users = users
		}
	}
	return cd
}

// updateCardData 更新 his
func updateCardData(rdb *redis.Client) {
	if rdb != nil {
		time.Sleep(time.Second)
		getCardDataFromRedis(rdb, true)
	}
}
